module klang.klang.转换工厂.转换为IR.Klang转换为IR_;
import 全局;
import std.conv: ·to = to;
import std.functional: ·fd = toDelegate;
import ··IR节点_ = klang.ir.语法节点.IR节点_;
import ··Klang节点_ = klang.klang.语法节点.Klang节点_;
import ··Triple = klang.编译.triple.Triple;
import ··目标_ = klang.目标.目标_;
import ··程序主机_ = klang.编译.主机.程序主机_;
import ··类型_ = klang.编译.类型.类型_;
import ··路径_ = klang.编译.路径.路径_;
import klang.编译.类型.类型_: 转换上下文_, 转换函数_, 输出解析器_, 转换支持_, 基工厂_ = 节点工厂_, 程序主机接口_, 前端接口_, 编译选项基类_, 基础符号_ = 符号_;
import klang.编译.类型.枚举值.枚举值_: SK;
import klang.编译.工具.工具_: getParseTreeNode_1;
import klang.编译.语法节点.节点_: 基础节点_ = 节点_, 基础源文件_ = 源文件_, 节点数组_;
import klang.klang.检查.klang检查_: Klang转换支持_;
import klang.klang.类型.klang类型_: KSK, klang编译选项_ = 编译选项_, 符号_ = Klang符号_;
import klang.klang.工具.klang工具_: 获取源文件的程序集;
import klang.编译.核心.核心_: 词典_, 整数_, 创建数组, 创建词典, 返回零值, 映射, 循环每个, 最小, 获取正规文件名函数_, 创建获取正规文件名函数, 查找索引, 结尾包含, 连接, 替换;
import klang.编译.节点访问.访问节点_: Visitor, visitNode, visitNodes;
import klang.klang.转换工厂.转换工具.Klang转换工具_: 获取输出文件名;
import 注册 = klang.编译.注册.注册_;
import klang.ir.节点工厂.IR工厂_: IR工厂_, 节点工厂标志_;
import klang.ir.类型.IR类型_: ISK, 节点标志_, IR编译选项_ = 编译选项_, 标识符分类_;
import klang.ir.语法节点.IR节点_: IR节点_, IR源文件_, IR令牌_, IR标识符_, 指针类型节点_ = 指针类型_, 整数类型节点_ = 整数类型_, 数组类型节点_ = 数组类型_, IR数字字面量_, 结构类型节点_ = 结构类型_, 函数类型节点_ = 函数类型_, 类型引用节点_ = 类型引用_, 类型声明节点_ = 类型声明_, IRc文本字面量_, c文本常量_, 全局表达式_, 本地线程设置_;
import klang.klang.语法节点.Klang节点_: Klang源文件_, 语句_, 版本语句_, 程序声明_, 表达式_, 符号引用表达式_, 前缀一元表达式_, 二元表达式_, 获取源文件;
import klang.编译.主机.程序主机_: 创建转换主机, 主机环境_, 重置主机环境, 恢复主机环境;
import klang.klang.转换工厂.转换为IR.类型.KToIR类型_: 未整合IR源文件_, 转译文本内容;
import klang.目标.目标_: AllocateTarget;
import klang.编译.系统.系统_: sys;
import klang.编译.路径.路径_: 获取相对路径从目录;
import klang.编译.输出节点.输出节点_: addSyntheticLeadingComment;
主机环境_ 储存的环境;
Klang源文件_ K当前源文件;
转换上下文_ K转换上下文;
输出解析器_ K解析器;
Klang转换支持_ klang检查;
klang编译选项_ klang选项;
程序主机接口_ klang主机;
前端接口_ IR前端;
程序主机接口_ IR主机;
编译选项基类_ IR选项;
词典_!(未整合IR源文件_) 生成的源文件组;
未整合IR源文件_ 当前未整合的源文件;
int 全局自动Id = 0;
dstring 包名;
dstring 程序名;
IR工厂_ fc;
class TC_ {
    this() { }
    static 整数类型节点_ s·IntN(uint n) {
        IR数字字面量_ i = fc.创建IR数字字面量(·to!(dstring)(n));
        return fc.创建整数类型(i);
    }
    static 指针类型节点_ s·Ptr(IR节点_ n, uint 地址 = ··null!(uint)) {
        if ((地址 !is ··null!(uint)) && 地址 != 0) {
            IR数字字面量_ i = fc.创建IR数字字面量(·to!(dstring)(地址));
            ··IR节点_.地址空间设置_ 地址节点 = fc.创建地址空间设置(i);
            return fc.创建指针类型(n, 地址节点);
        }
        return fc.创建指针类型(n);
    }
    static 数组类型节点_ s·At(IR节点_ t, ulong n) {
        IR数字字面量_ i = fc.创建IR数字字面量(·to!(dstring)(n));
        return TC_.s·At(t, i);
    }
    static 数组类型节点_ s·At(IR节点_ t, IR数字字面量_ n) {
        return fc.创建数组类型(t, n);
    }
    static 结构类型节点_ s·St(IR节点_[] tn) {
        tn = tn.dup;
        return fc.创建结构类型(fc.f·创建节点数组!(IR节点_)(tn, false));
    }
    static 节点数组_!(IR节点_) s·argsT(IR节点_[] t) {
        t = t.dup;
        return fc.f·创建节点数组!(IR节点_)(t, false);
    }
    static 函数类型节点_ s·Ft(IR节点_ r, bool IsVarArg, IR节点_[] args) {
        args = args.dup;
        return fc.创建函数类型(r, TC_.s·argsT(args), IsVarArg);
    }
    static IR令牌_!(ISK) s·Void() {
        return fc.转为令牌(ISK.void_);
    }
    static 类型引用节点_ s·ID(dstring 内容) {
        IR标识符_ id = fc.创建IR标识符(标识符分类_.类型标识符_, 内容);
        return fc.创建类型引用(id);
    }
}
转换函数_!(基础节点_) 转换IR(转换上下文_ ct) {
    .K转换上下文 = ct;
    .K解析器 = K转换上下文.getEmitResolver();
    K转换上下文.enabledSyntaxKindFeaturesRe();
    .klang检查 = (cast(Klang转换支持_)(K解析器.获取输出转换支持()));
    .klang主机 = K解析器.获取主机();
    .klang选项 = (cast(klang编译选项_)(klang主机.获取编译选项()));
    .包名 = klang选项.名称;
    .IR前端 = 注册.获取注册前端且执行初始化("ir"d);
    .IR选项 = .生成IR编译选项(.klang选项);
    .fc = new IR工厂_(节点工厂标志_.合成工厂_, 节点标志_.无);
    return cast(转换函数_!(基础节点_))(·fd(&.转换));
}
基础节点_[] 转换(基础节点_ n) {
    Klang源文件_ ks = 获取源文件(n);
    .转换源文件(ks);
    if ((ks.标志 & 节点标志_.节点组中最后一个) != 0) {
        .设置节点标志(ks, ~节点标志_.节点组中最后一个);
        .输出转换的IR文件();
    }
    return ··null!(基础节点_[]);
}
void 设置节点标志(基础节点_ n, 节点标志_ 标志) {
    n.标志 |= (cast(ulong)(标志));
}
void 输出转换的IR文件() {
    .储存的环境 = 重置主机环境();
    未整合IR源文件_[] uns = (cast(未整合IR源文件_[])(生成的源文件组.值组()));
    .IR主机 = 创建转换主机(.IR前端, .IR选项, cast(基础源文件_[])(映射!(未整合IR源文件_, IR源文件_)(uns, cast(IR源文件_ delegate(未整合IR源文件_, size_t))(·fd(&.转换未整合源文件为IR源文件)))));
    IR主机.输出();
    恢复主机环境(.储存的环境);
}
IR源文件_ 转换未整合源文件为IR源文件(未整合IR源文件_ us, size_t _) {
    基础源文件_ ks = us.整合的文件[0];
    IR源文件_ s = fc.创建IR源文件();
    s.文件名 = ks.文件名;
    IR节点_[] 语句组 = 创建数组!(IR节点_)();
    ··IR节点_.空语句_ 空语句 = fc.创建空语句();
    .追加!(IR节点_)(语句组, us.目标平台及源文件名组);
    if (us.目标平台及源文件名组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    .追加!(IR节点_)(语句组, us.类型声明组);
    if (us.类型声明组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    .追加!(IR节点_)(语句组, us.封装声明组);
    if (us.封装声明组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    .追加!(IR节点_)(语句组, us.全局声明组);
    if (us.全局声明组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    .追加!(IR节点_)(语句组, us.函数定义组);
    if (us.函数定义组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    .追加!(IR节点_)(语句组, us.函数声明组);
    if (us.函数声明组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    .追加!(IR节点_)(语句组, us.特性声明组);
    if (us.特性声明组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    .追加!(IR节点_)(语句组, us.元数据声明组);
    if (us.元数据声明组.length > 0) {
        .追加!(IR节点_)(语句组, 空语句);
    }
    s.语句组 = ·to!(节点数组_!(基础节点_))(fc.f·创建节点数组!(IR节点_)(new 节点数组_!(IR节点_)(语句组)));
    return s;
}
Klang源文件_ 转换源文件(Klang源文件_ n) {
    n.标志 |= (cast(整数_)(节点标志_.不输出文件));
    .K当前源文件 = n;
    .创建或获取未整合源文件(n);
    .生成文件名(n);
    .生成数据布局(.klang选项);
    .生成目标平台(.klang选项);
    .生成固定内容();
    visitNodes!(基础节点_)(n.语句组, cast(Visitor)(·fd(&.访问语句)));
    return ··null!(Klang源文件_);
}
基础节点_ 访问语句(基础节点_ n) {
    switch (n.目标种类) {
        case KSK.程序声明: {
            return .访问程序声明((cast(程序声明_)(n)));
        }
        case KSK.导入从声明:
        case KSK.导入声明:
        case KSK.别名声明:
        case KSK.类型声明:
        case KSK.对象声明:
        case KSK.结构声明:
        case KSK.函数声明:
        case KSK.变量声明:
        case KSK.测试单元语句:
        default: break;
    }
    return ··null!(基础节点_);
}
基础节点_ 访问程序声明(程序声明_ n) {
    符号_ 程序符号 = klang检查.获取合并符号(.获取原始节点(n).符号);
    .创建模块类型(n);
    visitNodes!(··Klang节点_.Klang节点_)(n.语句组, cast(Visitor)(·fd(&.访问语句)));
    return ··null!(基础节点_);
}
void 创建模块类型(程序声明_ n) {
    ··Klang节点_.Klang标识符_ 名称 = n.名称;
    dstring[] 模块名称组 = 创建数组!(dstring)();
    if (.包名 !is ··null!(dstring)) {
        .追加!(dstring)(模块名称组, .包名);
    }
    if (名称 !is ··null!(··Klang节点_.Klang标识符_)) {
        .追加!(dstring)(模块名称组, 名称.标识符.内容);
    }
    else {
        .追加!(dstring)(模块名称组, "启动"d);
    }
    dstring 模块名 = 连接(模块名称组, "."d);
    dstring 不转义模块名 = 模块名;
    uint 长度 = 0;
    模块名 = 转译文本内容(模块名, 长度);
    .程序名 = 模块名;
    dstring n2 = 模块名 ~ "__ModuleInfoZ"d;
    .追加!(IR节点_)(当前未整合的源文件.封装声明组, fc.创建封装声明(fc.创建IR标识符(标识符分类_.封装标识符_ | 标识符分类_.文本内容标识符_, n2), fc.转为令牌(ISK.any)));
    ++长度;
    模块名 ~= "\\00"d;
    数组类型节点_ t = TC_.s·At(TC_.s·IntN(8), 长度);
    IRc文本字面量_ 值 = fc.创建IRc文本字面量(·to!(string)(不转义模块名), 模块名);
    全局表达式_ st_0 = fc.创建全局表达式(TC_.s·IntN(32), fc.创建IR数字字面量("-2147483644"d));
    全局表达式_ st_1 = fc.创建全局表达式(TC_.s·IntN(32), fc.创建IR数字字面量("0"d));
    全局表达式_ st_2 = fc.创建全局表达式(t, fc.创建c文本常量(值));
    IR标识符_ 类型名称 = .创建自动类型名();
    ··IR节点_.全局变量声明_ ModuleInfoZ = fc.创建全局变量声明(类型名称, fc.转为令牌(ISK.global), fc.创建IR标识符(标识符分类_.全局标识符_ | 标识符分类_.文本内容标识符_, n2), 返回零值!(IR节点_)(), 返回零值!(IR节点_)(), 返回零值!(IR节点_)(), 返回零值!(IR节点_)(), 返回零值!(本地线程设置_)(), 返回零值!(IR节点_)(), 返回零值!(IR节点_)(), 返回零值!(IR节点_)(), fc.创建结构常量表达式(new 节点数组_!(IR节点_)([st_0, st_1, st_2]), false), 返回零值!(IR节点_)(), 返回零值!(IR节点_)(), 返回零值!(IR节点_)(), fc.创建封装设置());
    .追加!(IR节点_)(当前未整合的源文件.全局声明组, ModuleInfoZ);
    整数类型节点_ I32 = TC_.s·IntN(32);
    类型声明节点_ 类型声明 = fc.创建类型声明(类型名称, TC_.s·St([I32, I32, t]));
    .追加前面!(IR节点_)(当前未整合的源文件.类型声明组, [类型声明]);
}
T[] 追加前面(T)(ref T[] 数组, T[] arr) {
    arr = arr.dup;
    T[] n = .追加!(T)(arr, 数组);
    数组 = n;
    return 数组;
}
dstring 全局ID() {
    dstring n = ·to!(dstring)(.全局自动Id);
    ++全局自动Id;
    return n;
}
IR编译选项_ 生成IR编译选项(klang编译选项_ k) {
    return new IR编译选项_("ir"d);
}
void 生成目标平台(klang编译选项_ k) {
    ··Triple.Triple T = k.目标平台;
    if (T !is ··null!(··Triple.Triple)) {
        ··IR节点_.IR文本字面量_ 值 = fc.创建IR文本字面量(T.Data);
        ··IR节点_.平台设置_ 平台设置 = fc.创建平台设置(值);
        ··IR节点_.目标语句_ 目标平台语句 = fc.创建目标语句(平台设置);
        .追加!(IR节点_)(当前未整合的源文件.目标平台及源文件名组, 目标平台语句);
    }
}
void 生成数据布局(klang编译选项_ k) {
    ··Triple.Triple T = k.目标平台;
    if (T is ··null!(··Triple.Triple)) {
        return;
    }
    ··目标_.TargetInfo 目标信息 = AllocateTarget(T);
    if ((目标信息 !is ··null!(··目标_.TargetInfo)) && (目标信息.DataLayoutString !is ··null!(dstring))) {
        ··IR节点_.IR文本字面量_ 值 = fc.创建IR文本字面量(目标信息.DataLayoutString);
        ··IR节点_.数据布局设置_ 布局设置 = fc.创建数据布局设置(值);
        ··IR节点_.目标语句_ 目标布局语句 = fc.创建目标语句(布局设置);
        .追加!(IR节点_)(当前未整合的源文件.目标平台及源文件名组, 目标布局语句);
    }
}
void 生成文件名(Klang源文件_ s) {
    ··路径_.路径_ 文件名 = s.文件名;
    dstring 相对路径 = .获取相对路径(s.文件名);
    ··IR节点_.IR文本字面量_ 值 = fc.创建IR文本字面量(.编码文件名(相对路径));
    ··IR节点_.源码文件名语句_ 源文件名称 = fc.创建源码文件名语句(值);
    .添加合成注释(源文件名称, "模块ID = "d ~ 相对路径);
    .追加!(IR节点_)(当前未整合的源文件.目标平台及源文件名组, 源文件名称);
}
void 生成固定内容() {
    .追加!(IR节点_)(当前未整合的源文件.类型声明组, .创建结构类型信息类型());
    .追加!(IR节点_)(当前未整合的源文件.类型声明组, .创建类型信息());
    .追加!(IR节点_)(当前未整合的源文件.类型声明组, .创建模块信息());
}
dstring 获取相对路径(dstring 文件名) {
    dstring 当前目录 = klang主机.获取当前目录();
    获取正规文件名函数_ 获取正规文件名 = 创建获取正规文件名函数(sys.是使用区分大小写文件系统);
    dstring 相对路径 = 获取相对路径从目录(当前目录, 文件名, cast(获取正规文件名函数_)(获取正规文件名));
    相对路径 = 替换(相对路径, "/"d, "\\"d);
    return 相对路径;
}
dstring 编码文件名(dstring 相对路径) {
    uint n = 0;
    return 转译文本内容(相对路径, n);
}
dstring 获取符号Id(基础符号_ s) {
    return ·to!(dstring)(klang检查.获取符号Id((cast(符号_)(s))));
}
基础节点_ 获取原始节点(基础节点_ n) {
    return getParseTreeNode_1(n);
}
void 创建或获取未整合源文件(Klang源文件_ k) {
    程序声明_ 程序声明 = 获取源文件的程序集(k);
    符号_ 合并的符号 = klang检查.获取合并符号(.获取原始节点(程序声明).符号);
    未整合IR源文件_ ns;
    dstring id = .获取符号Id(合并的符号);
    if ((.生成的源文件组 is null) || (.生成的源文件组.原型 is ··null!(未整合IR源文件_[dstring])) || !生成的源文件组.具有(id)) {
        if ((.生成的源文件组 is null) || (.生成的源文件组.原型 is ··null!(未整合IR源文件_[dstring]))) {
            .生成的源文件组 = 创建词典!(未整合IR源文件_)();
        }
        ns = new 未整合IR源文件_();
        .追加!(基础源文件_)(ns.整合的文件, k);
        生成的源文件组.p·设置(id, ns);
    }
    else {
        ns = 生成的源文件组.获取(id);
        .追加!(基础源文件_)(ns.整合的文件, k);
    }
    .当前未整合的源文件 = ns;
}
void 添加合成注释(基础节点_ n, dstring 内容) {
    addSyntheticLeadingComment(n, SK.单行注释, " "d ~ 内容, true);
}
IR标识符_ 创建结构类型信息名称() {
    return fc.创建IR标识符(标识符分类_.类型标识符_, "object.TypeInfo_Struct"d);
}
// %object.TypeInfo_Struct
类型声明节点_ 创建结构类型信息类型() {
    整数类型节点_ i8 = TC_.s·IntN(8);
    // i8*
    指针类型节点_ I8p = TC_.s·Ptr(i8);
    // [19 x i8*]*
    指针类型节点_ st_0 = TC_.s·Ptr(TC_.s·At(I8p, 19));
    // i8*
    指针类型节点_ st_1 = I8p;
    // {i64, i8*}
    结构类型节点_ st_2 = TC_.s·St([TC_.s·IntN(64), I8p]);
    // {i64, i8*}
    结构类型节点_ st_3 = st_2;
    // i64 (i8*)*
    指针类型节点_ st_4 = TC_.s·Ptr(TC_.s·Ft(TC_.s·IntN(64), false, [I8p]));
    // i1 (i8*, i8*)*
    指针类型节点_ st_5 = TC_.s·Ptr(TC_.s·Ft(TC_.s·IntN(1), false, [I8p, I8p]));
    // i32 (i8*, i8*)*
    指针类型节点_ st_6 = TC_.s·Ptr(TC_.s·Ft(TC_.s·IntN(32), false, [I8p, I8p]));
    // {i64, i8*} (i8*, i8*)*
    指针类型节点_ st_7 = TC_.s·Ptr(TC_.s·Ft(st_2, false, [I8p, I8p]));
    // i32
    整数类型节点_ st_8 = TC_.s·IntN(32);
    // [4 x i8]
    数组类型节点_ st_9 = TC_.s·At(i8, 4);
    // void (i8*)*
    指针类型节点_ st_10 = TC_.s·Ptr(TC_.s·Ft(TC_.s·Void(), false, [I8p]));
    // void (i8*)*
    指针类型节点_ st_11 = TC_.s·Ptr(TC_.s·Ft(TC_.s·Void(), false, [I8p]));
    // i32
    整数类型节点_ st_12 = TC_.s·IntN(32);
    // [4 x i8]
    数组类型节点_ st_13 = TC_.s·At(i8, 4);
    // %object.TypeInfo*
    指针类型节点_ st_14 = TC_.s·Ptr(TC_.s·ID("object.TypeInfo"d));
    指针类型节点_ st_15 = st_14;
    指针类型节点_ st_16 = I8p;
    结构类型节点_ st = TC_.s·St([st_0, st_1, st_2, st_3, st_4, st_5, st_6, st_7, st_8, st_9, st_10, st_11, st_12, st_13, st_14, st_15, st_16]);
    return fc.创建类型声明(.创建结构类型信息名称(), st);
}
IR标识符_ 创建类型信息名称() {
    return fc.创建IR标识符(标识符分类_.类型标识符_, "object.TypeInfo"d);
}
// %object.TypeInfo
类型声明节点_ 创建类型信息() {
    整数类型节点_ i8 = TC_.s·IntN(8);
    // i8*
    指针类型节点_ I8p = TC_.s·Ptr(i8);
    // [19 x i8*]*
    指针类型节点_ st_0 = TC_.s·Ptr(TC_.s·At(I8p, 19));
    // i8*
    指针类型节点_ st_1 = I8p;
    结构类型节点_ st = TC_.s·St([st_0, st_1]);
    return fc.创建类型声明(.创建类型信息名称(), st);
}
IR标识符_ 创建自动类型名() {
    return fc.创建IR标识符(标识符分类_.类型标识符_, .全局ID());
}
IR标识符_ 创建模块信息名称() {
    return fc.创建IR标识符(标识符分类_.类型标识符_, "object.ModuleInfo"d);
}
// %object.ModuleInfo
类型声明节点_ 创建模块信息() {
    整数类型节点_ i32_ = TC_.s·IntN(32);
    结构类型节点_ st = TC_.s·St([i32_, i32_]);
    return fc.创建类型声明(.创建模块信息名称(), st);
}
